/*
 * Ken Anderson, 2010
 */

#ifndef RENDERER_H
#define RENDERER_H

#ifdef WIN32
# include "SDL.h"
# include "SDL_OpenGL.h"
# include "FTGL/ftgl.h"		// For text
#else
# include <SDL/SDL.h>
# include <SDL/SDL_opengl.h>
# include <FTGL/ftgl.h>		// For text
#endif
#include "Graph.h"
#include "Heuristic.h"
#include "Search.h"
#include "EventHandler.h"	//Only for WorldState class is in it's own file.

#define COLOR_HEURISTIC		true
#define FONT_NAME			"../Fonts/cour.ttf"
#define MAX_WHITENESS		0.8
#define FOV					45
#define BOUNDING_BOX_BUFFER	0.5
#define SPACE_BETWEEN_LEVEL	5.0f
#define MIN_XY				-99999.0
#define MAX_XY				99999.0

enum Color { RED, GREEN, BLUE };
enum ColoringMethod { NONE, COLOR_F_VALUE, COLOR_G_VALUE, COLOR_NUM_EXPANSIONS };

// The bounding box surrounds our simulation.
// Anything outside the box will not show.
class BoundingBox
{
public:
	float minX;
	float minY;
	float maxX;
	float maxY;

	BoundingBox() {
		maxX = MIN_XY;
		maxY = MIN_XY;
		minX = MAX_XY;
		minY = MAX_XY;
	}
	~BoundingBox() {};
	float centerX() { return (float)(maxX-minX)/2.0f + minX; }
	float centerY() { return (float)(maxY-minY)/2.0f + minY; }
	float width()   { return maxX-minX; };
	float height()  { return maxY-minY; };
};

// Wrapper around OpenGL routines.  
// Provides basic rendering of our objects.
// Immediate mode rendering and display lists are currently used because it's simpler
// and we have many changes in the environment.
// In the future, however, look into using Vertex Buffer Objects (VBOs) to speed up rendering.
class Renderer
{
	friend class Visualizer;

private:

	GLuint mNodeGeometryIndex;	// Speed up drawing of objects
	BoundingBox mGraphBoundingBox;
	WorldState * mWorldState;
	static const ColoringMethod mColoringMethod = NONE;
	FTFont * mFont;

	void InitializeOpenGL();
	void InitializeText( const char * fontFileName = FONT_NAME );
	void PreDraw();
	void DrawNodes( Graph * graph, GLfloat z );
	void DrawNodes( Heuristic * heuristic, GLfloat z );
	void DrawNodes( Search * search, GLfloat z );
	void DrawEdges( Graph * graph, GLfloat z );
	void DrawSolutionPath( Search * search, GLfloat z );
	void Draw2DText( Search * search = NULL );
	void PostDraw();

	void SetColor( GLfloat value, GLfloat minValue, GLfloat maxValue, Color color );
	void DrawCoordinate(GLfloat x, GLfloat y, GLfloat z );
	void DrawEdge(GLfloat startX, GLfloat startY, GLfloat endX, GLfloat endY, GLfloat z);

public:
	Renderer( WorldState * worldState ); 
	virtual ~Renderer();

	void Initialize( Graph * graph );
	void SetPerspective();

	void Render(Graph * graph);
	void Render(Heuristic * heuristic);
	void Render(Search * search);
};

#endif
